#ifndef MD5_H
#define MD5_H

#include "base_type.h"
#include <string>
#include <fstream>

/* Type define */
typedef unsigned char byte;
typedef unsigned long ulong;

using std::string;
using std::ifstream;

/* MD5 declaration. */
class MD5 {
public:
	MD5( );
	MD5( const void * input, size_t length );
	MD5( const string &str );
	MD5( ifstream &in );
	MD5( const MD5& );
	MD5& operator=( const MD5& );

public:
	
	void update( const void *input, size_t length );
	void update( const string &str );
	void update( ifstream &in );
	const byte * digest( );
	string_t toString( );
	void reset( );

	static size_t HexStringToBytes( const byte * input, size_t in_len, byte * output, size_t out_len );
private:
	void update( const byte *input, size_t length );
	void final( );
	void transform( const byte block[64] );
	void encode( const ulong *input, byte *output, size_t length );
	void decode( const byte *input, ulong *output, size_t length );
	string_t bytesToHexString( const byte *input, size_t length );

	/* class uncopyable */
	
private:
	ulong _state[4];	/* state ( ABCD ) */
	ulong _count[2];	/* number of bits, modulo 2^64 ( low-order word first ) */
	byte _buffer[64];	/* input buffer */
	byte _digest[16];	/* message digest */
	bool _finished;		/* calculate finished ? */

	static const byte PADDING[64];	/* padding for calculate */
	static const char_t HEX[16];
//	static const size_t BUFFER_SIZE = 1024;
};

#endif/*MD5_H*/